package config

import (
	"log"
	"time"
	"github.com/glacjay/goini"
    "os"
    "path/filepath"
)

type Board struct {
	DbName       string
	Pghost       string
	TemplatePath string
	ThumbDir     string
	ImgDir       string
    ReportMax    int
    SMTPServer   string

    SearchPosts  int
    SearchPages  int
	ImgRetry     int
	FtsMaxWords  int
	Abbrev       string
	Url          string
	Title        string
	StartIndex   int
	EndIndex     int
	LastPage     int

	BoardRefreshMin time.Duration // All these Min/Max fields are in seconds
	BoardRefreshMax time.Duration
	BoardBackoff    float64

	ThreadRefreshMin time.Duration
	ThreadRefreshMax time.Duration
	ThreadBackoff    float64

	FetchThumbnails bool
	FetchImages     bool

	BoardPageCacheTime  time.Duration
	ThreadCacheTime     time.Duration
	SearchCacheTime     time.Duration
	UserDataHoldTime    time.Duration
    MinReqWaitTime      time.Duration
    MaxUserRequests     int

    ThreadsPerPage  int
    TailLength      int
    NumberOfPages   int

    GhostMinLength  int
    GhostMaxLength  int

    ImgNameCutoff   int
    Site            string
    TableName       string
    FromEmail       string
    NotifyAddr    string
    NotifyPass      string
    AutoPurgeTime   time.Duration
}

var Defaults *Board
var Boards map[string]*Board

func setGeneral(conf ini.Dict) {
    log.Print("Loading general config...")
    log.Print("General config OK")
}

// Set board defaults. If a field is not found, fallback to the default set in
// 'fb'. If the value doesn't exist there either, panic.
func setBoard(conf ini.Dict, fb map[string]string, name string) *Board {
    var b Board
    b.Abbrev = name
    b.DbName          = conf.GetString(   name, "database_name",        fb)
    b.Pghost          = conf.GetString(   name, "pghost",               fb)
    b.TemplatePath    = conf.GetString(   name, "template_path",        fb)
    b.ThumbDir        = conf.GetString(   name, "thumbnail_directory",  fb)
    b.ImgDir          = conf.GetString(   name, "image_directory",      fb)
    b.Url             = conf.GetString(   name, "url",                  fb)
    b.Title           = conf.GetString(   name, "title",                fb)
    b.Site            = conf.GetString(   name, "site",                 fb)
    b.SMTPServer      = conf.GetString(   name, "smtp_server",          fb)
    b.FromEmail       = conf.GetString(   name, "from_email",           fb)
    b.NotifyAddr      = conf.GetString(   name, "notification_address", fb)
    b.NotifyPass      = conf.GetString(   name, "notification_password",fb)
    b.FetchThumbnails = conf.GetBool(     name, "fetch_thumbnails",     fb)
    b.FetchImages     = conf.GetBool(     name, "fetch_images",         fb)
    b.StartIndex      = conf.GetInt(      name, "start_index",          fb)
    b.EndIndex        = conf.GetInt(      name, "end_index",            fb)
    b.ThreadsPerPage  = conf.GetInt(      name, "threads_per_page",     fb)
    b.TailLength      = conf.GetInt(      name, "tail_length",          fb)
    b.LastPage        = conf.GetInt(      name, "last_page",            fb)
    b.NumberOfPages   = conf.GetInt(      name, "number_of_pages",      fb)
    b.SearchPosts     = conf.GetInt(      name, "search_show_posts",    fb)
    b.SearchPages     = conf.GetInt(      name, "search_show_pages",    fb)
    b.ImgRetry        = conf.GetInt(      name, "image_retry",          fb)
    b.FtsMaxWords     = conf.GetInt(      name, "fts_max_words",        fb)
    b.GhostMinLength  = conf.GetInt(      name, "ghost_min_post_length",fb)
    b.GhostMaxLength  = conf.GetInt(      name, "ghost_max_post_length",fb)
    b.ImgNameCutoff   = conf.GetInt(      name, "image_name_cutoff",    fb)
    b.MaxUserRequests = conf.GetInt(      name, "max_user_requests",    fb)
    b.ReportMax       = conf.GetInt(      name, "max_user_reports",     fb)
    b.BoardBackoff    = conf.GetDouble(   name, "board_backoff",        fb)
    b.ThreadBackoff   = conf.GetDouble(   name, "thread_backoff",       fb)
    brmin             := conf.GetDouble(  name, "board_refresh_min",    fb)
    brmax             := conf.GetDouble(  name, "board_refresh_max",    fb)
    trmin             := conf.GetDouble(  name, "thread_refresh_min",   fb)
    trmax             := conf.GetDouble(  name, "thread_refresh_max",   fb)
    bpctime           := conf.GetDouble(  name, "board_page_cache_time",fb)
    tctime            := conf.GetDouble(  name, "thread_cache_time",    fb)
    sctime            := conf.GetDouble(  name, "search_cache_time",    fb)
    udhtime           := conf.GetDouble(  name, "user_data_hold_time",  fb)
    mrwtime           := conf.GetDouble(  name, "min_request_wait_time",fb)
    aptime            := conf.GetDouble(  name, "autopurge_time",       fb)
    b.BoardRefreshMin       = time.Duration(brmin   * float64(time.Minute))
    b.BoardRefreshMax       = time.Duration(brmax   * float64(time.Minute))
    b.ThreadRefreshMin      = time.Duration(trmin   * float64(time.Minute))
    b.ThreadRefreshMax      = time.Duration(trmax   * float64(time.Minute))
    b.BoardPageCacheTime    = time.Duration(bpctime * float64(time.Minute))
    b.ThreadCacheTime       = time.Duration(tctime  * float64(time.Minute))
    b.SearchCacheTime       = time.Duration(sctime  * float64(time.Minute))
    b.UserDataHoldTime      = time.Duration(udhtime * float64(time.Minute))
    b.AutoPurgeTime         = time.Duration(aptime * float64(time.Minute))
    b.MinReqWaitTime        = time.Duration(mrwtime * float64(time.Second))
    b.TableName             = b.Abbrev+"_"+b.Site
    log.Print("Board "+name+" config OK")
    return &b
}

// Read board configs. Normal boards fall backon _default_ for missing
// settings. _default_ falls back on nothing and fails if something is not
// present.
func readConfig() {
    conf, err := ini.Load(".nihrc")
	if err != nil {
        home := os.Getenv("HOME")
        conf, err = ini.Load( filepath.Join(home, ".nihrc") )
        if err != nil {
            log.Panic("Could not read config file : " + err.Error())
        }
	}

    emptyMap := make(map[string]string)
    Defaults = setBoard(conf, emptyMap, "_default_")

    Boards = make(map[string]*Board)
    for _, section := range conf.GetSections() {
        if section != ""  && section != "_default_" {
            b := setBoard(conf, conf["_default_"], section)
            Boards[b.TableName] = b
        }
    }
}

func init() {
    readConfig()
}

